package com.example.demo.stream.collector;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.IntStream;

/**
 * @author MarioZzz
 * @create 2023-10-24 17:00
 */
public class Main {

    public static void main(String[] args) {
        Main main = new Main();
        main.run();
        System.out.println("原始数据：");
        main.nums.forEach(i -> System.out.print(i + " "));
        System.out.println("\n\ncollect方法加工后的数据：");
        main.result.forEach(i -> System.out.print(i + " "));
    }

    private List<Integer> nums = new ArrayList<>();
    private Set<Double> result = new HashSet<>();

    public void run() {
        // 填充原始数据，nums中填充0-9 10个数
        IntStream.range(0, 10).forEach(nums::add);
        //实现Collector接口
        result = nums.stream().parallel().collect(new Collector<
                //流中的元素类型
                Integer,
                //累加器类型
                Container,
                //collect操作的结果类型
                Set<Double>>() {

            @Override
            public Supplier<Container> supplier() {
                return Container::new;
            }

            @Override
            public BiConsumer<Container, Integer> accumulator() {
                //业务逻辑写在这里
                return Container::accumulate;
            }

            @Override
            public BinaryOperator<Container> combiner() {
                return Container::combine;
            }

            @Override
            public Function<Container, Set<Double>> finisher() {
                return Container::getResult;
            }

            @Override
            public Set<Characteristics> characteristics() {
                // 固定写法
                return Collections.emptySet();
            }
        });
    }

    static class Container {
        // 定义本地的result
        public Set<Double> set;

        private Compute compute = new Compute();

        public Container() {
            this.set = new HashSet<>();
        }

        public Container accumulate(int num) {
            this.set.add(compute.compute(num));
            return this;
        }

        public Container combine(Container container) {
            this.set.addAll(container.set);
            return this;
        }

        public Set<Double> getResult() {
            return this.set;
        }
    }
}
